package com.lefevre.cms.web.action.common;


import com.lefevre.cms.bean.ErrorView;
import com.lefevre.cms.bean.setting.AllowRegisterAccount;
import com.lefevre.cms.bean.setting.SystemSetting;
import com.lefevre.cms.bean.thirdParty.WeChatConfig;
import com.lefevre.cms.bean.thirdParty.WeiXinOpenId;
import com.lefevre.cms.bean.thirdParty.WeiXinUserInfo;
import com.lefevre.cms.bean.user.AccessUser;
import com.lefevre.cms.bean.user.RefreshUser;
import com.lefevre.cms.bean.user.User;
import com.lefevre.cms.bean.user.UserLoginLog;
import com.lefevre.cms.service.setting.SettingService;
import com.lefevre.cms.service.theme.ThemeService;
import com.lefevre.cms.service.user.UserService;
import com.lefevre.cms.utils.*;
import com.lefevre.cms.utils.threadLocal.AccessUserThreadLocal;
import com.lefevre.cms.web.action.AccessDeviceUtil;
import com.lefevre.cms.web.action.CSRFTokenManage;
import com.lefevre.cms.web.action.fileSystem.FileManage;
import com.lefevre.cms.web.action.membershipCard.MembershipCardGiftTaskManage;
import com.lefevre.cms.web.action.setting.SettingManage;
import com.lefevre.cms.web.action.theme.TemplateMain;
import com.lefevre.cms.web.action.thirdParty.ThirdPartyManage;
import com.lefevre.cms.web.action.user.UserLoginLogManage;
import com.lefevre.cms.web.action.user.UserManage;
import com.lefevre.cms.web.taglib.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * 第三方服务管理
 */
@Controller
public class ThirdPartyFormAction {

    @Resource
    CSRFTokenManage csrfTokenManage;
    @Resource
    ThemeService themeService;
    @Resource
    TemplateMain templateMain;
    @Resource
    ThirdPartyManage thirdPartyManage;
    @Resource
    AccessDeviceUtil accessDeviceUtil;
    @Resource
    SettingService settingService;
    @Resource
    UserService userService;
    @Resource
    UserManage userManage;
    @Resource
    UserLoginLogManage userLoginLogManage;
    @Resource
    OAuthManage oAuthManage;
    @Resource
    SettingManage settingManage;
    @Resource
    FileManage fileManage;
    @Resource
    MembershipCardGiftTaskManage membershipCardGiftTaskManage;

    /**
     * 查询微信openid
     *
     * @param code code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期
     */
    @RequestMapping(value = "/thirdParty/queryWeiXinOpenId", method = RequestMethod.POST)
    @ResponseBody
    public String queryWeiXinOpenId(ModelMap model, String code,
                                    HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (code != null && !"".equals(code.trim())) {

            WeiXinOpenId oldWeiXinOpenId = thirdPartyManage.getWeiXinOpenId(code.trim());
            if (oldWeiXinOpenId != null) {
                //只允许查一次
                thirdPartyManage.deleteWeiXinOpenId(code.trim());
                return JsonUtils.toJSONString(oldWeiXinOpenId);
            } else {
                WeiXinOpenId weiXinOpenId = thirdPartyManage.queryWeiXinOpenId(code.trim());
                if (weiXinOpenId != null) {
                    return JsonUtils.toJSONString(weiXinOpenId);
                }
            }
        }
        return "";
    }


    /**
     * 第三方登录链接
     *
     * @param model
     * @param interfaceProduct 接口产品
     * @param jumpUrl          重定向参数
     * @param redirectAttrs
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/thirdParty/loginLink", method = RequestMethod.GET)
    public String loginLink(ModelMap model, Integer interfaceProduct, String jumpUrl,
                            RedirectAttributes redirectAttrs,
                            HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (interfaceProduct != null && interfaceProduct.equals(10)) {//微信
            if (accessDeviceUtil.accessDevices(request).equals("pc")) {//电脑端
                WeChatConfig weChatConfig = thirdPartyManage.queryWeChatConfig();
                if (weChatConfig != null) {
                    String appid = weChatConfig.getOp_appID();//开放平台唯一标识

                    String redirect_uri = Configuration.getUrl(request) + "thirdParty/loginRedirect";

                    if (jumpUrl != null && !"".equals(jumpUrl.trim())) {
                        redirect_uri = Configuration.getUrl(request) + "thirdParty/loginRedirect?jumpUrl=" + jumpUrl.trim();//Base64安全编码;
                    }
                    redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");
                    String state = csrfTokenManage.getToken(request);//获取令牌;

                    return "redirect:https://open.weixin.qq.com/connect/qrconnect?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_login&state=" + state + "#wechat_redirect";

                }
            } else if (accessDeviceUtil.accessDevices(request).equals("wap")) {//手机端
                WeChatConfig weChatConfig = thirdPartyManage.queryWeChatConfig();
                if (weChatConfig != null) {
                    String appid = weChatConfig.getOa_appID();//公众号唯一标识

                    String redirect_uri = Configuration.getUrl(request) + "thirdParty/loginRedirect";

                    if (jumpUrl != null && !"".equals(jumpUrl.trim())) {
                        redirect_uri = Configuration.getUrl(request) + "thirdParty/loginRedirect?jumpUrl=" + jumpUrl.trim();//Base64安全编码;
                    }
                    redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");

                    String state = csrfTokenManage.getToken(request);//获取令牌;

                    return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=" + state + "&connect_redirect=1#wechat_redirect";

                }
            }

        }

        //当前模板使用的目录
        String dirName = themeService.findTemplateDir_cache();

        model.addAttribute("message", "第三方登录链接错误");//返回消息
        return "/templates/" + dirName + "/" + accessDeviceUtil.accessDevices(request) + "/message";
    }


    /**
     * 第三方登录重定向
     *
     * @param model
     * @param code          微信公众号code
     * @param state         微信公众号state 存放csrf令牌
     * @param jumpUrl       重定向参数
     * @param redirectAttrs
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/thirdParty/loginRedirect")
    public String loginRedirect(ModelMap model, String code, String state, String jumpUrl,
                                RedirectAttributes redirectAttrs,
                                HttpServletRequest request, HttpServletResponse response) throws Exception {

        Map<String, String> error = new HashMap<>();

        //判断令牌
        if (state != null && !"".equals(state.trim())) {
            String token_sessionid = csrfTokenManage.getToken(request);//获取令牌
            if (token_sessionid != null && !"".equals(token_sessionid.trim())) {
                if (!token_sessionid.equals(state)) {
                    error.put("token", ErrorView._13.name());
                }
            } else {
                error.put("token", ErrorView._12.name());
            }
        } else {
            error.put("token", ErrorView._11.name());
        }

        if (error.size() == 0) {
            WeChatConfig weChatConfig = thirdPartyManage.queryWeChatConfig();
            if (weChatConfig != null) {
                String appid = "";//应用唯一标识
                String secret = "";//应用密钥

                if (accessDeviceUtil.accessDevices(request).equals("pc")) {//电脑端
                    appid = weChatConfig.getOp_appID();
                    secret = weChatConfig.getOp_appSecret();
                } else if (accessDeviceUtil.accessDevices(request).equals("wap")) {//手机端
                    //微信浏览器端
                    appid = weChatConfig.getOa_appID();
                    secret = weChatConfig.getOa_appSecret();
                }

                if (appid != null && !"".equals(appid.trim()) && secret != null && !"".equals(secret.trim())) {
                    WeiXinUserInfo weiXinUserInfo = thirdPartyManage.queryWeiXinUserInfo(code, appid, secret);
                    if (weiXinUserInfo != null) {
                        if (weiXinUserInfo.getErrorCode() == null || "".equals(weiXinUserInfo.getErrorCode())) {


                            if (weiXinUserInfo.getUnionId() != null && !"".equals(weiXinUserInfo.getUnionId())) {
                                this.createUserInfo(weiXinUserInfo.getUnionId(), weiXinUserInfo.getOpenId(), error, request, response);


                                if (error.size() == 0) {
                                    //重定向到
                                    if (jumpUrl != null && !"".equals(jumpUrl.trim())) {

                                        //Base64解码后参数进行URL编码
                                        String parameter = WebUtil.parameterEncoded(Base64.decodeBase64URL(jumpUrl));

                                        String encodedRedirectURL = response.encodeRedirectURL(parameter);


                                        response.sendRedirect((Configuration.getPath() != null && !"".equals(Configuration.getPath()) ? Configuration.getPath() + "/" : "/") + encodedRedirectURL);
                                        return null;

                                    } else {
                                        return "redirect:/index";

                                    }
                                }


                            } else {
                                error.put("weiXinUserInfo", "微信unionid为空，请将公众号绑定到微信开放平台");
                            }
                        } else {
                            error.put("weiXinUserInfo", weiXinUserInfo.getErrorCode() + " -- " + weiXinUserInfo.getErrorMessage());
                        }
                    } else {

                        error.put("weiXinUserInfo", "查询微信用户基本信息为空");
                    }
                }


            } else {
                error.put("weChatConfig", "微信配置信息不存在");
            }


        }

        Map<String, String> returnError = new HashMap<>();
        if (error.size() > 0) {
            //将枚举数据转为错误提示字符
            for (Map.Entry<String, String> entry : error.entrySet()) {
                if (ErrorView.get(entry.getValue()) != null) {
                    returnError.put(entry.getKey(), ErrorView.get(entry.getValue()));
                } else {
                    returnError.put(entry.getKey(), entry.getValue());
                }

            }
            if (accessDeviceUtil.accessDevices(request).equals("wap")) {//单页使用
                String htmlContent = "<html><head><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'><style type='text/css'>html,body{height: 100%; margin: 0;padding: 0;}</style></head>"
                        + "<body><div style='width: 100%;height: 100%;display:flex; justify-content:center;align-items:center; font-size: 16px;color: #666;'>"
                        + returnError.entrySet().iterator().next().getValue()
                        + "</div></body></html>";

                WebUtil.writeToWeb(htmlContent, "html", response);
                return null;

            }
        }


        model.addAttribute("message", "登录重定向失败");//返回消息
        if (error.size() > 0) {
            model.addAttribute("message", returnError.entrySet().iterator().next().getValue());//返回消息
        }
        //当前模板使用的目录
        String dirName = themeService.findTemplateDir_cache();
        return "/templates/" + dirName + "/" + accessDeviceUtil.accessDevices(request) + "/message";

    }

    /**
     * 生成第三方用户信息
     *
     * @param unionId 第三方用户信息唯一凭证
     * @param openId  用户的唯一标识
     * @param error   错误信息集合
     */
    private void createUserInfo(String unionId, String openId, Map<String, String> error,
                                HttpServletRequest request, HttpServletResponse response) {

        String platformUserId = userManage.thirdPartyUserIdToPlatformUserId(unionId, 40);
        User user = userService.findUserByPlatformUserId(platformUserId);


        SystemSetting systemSetting = settingService.findSystemSetting_cache();
        if (systemSetting.getCloseSite().equals(2)) {
            error.put("weiXinUserInfo", ErrorView._21.name());//只读模式不允许提交数据
        } else {
            if (user == null) {//用户不存在，执行注册

                //读取允许注册账号类型
                AllowRegisterAccount allowRegisterAccount = settingManage.readAllowRegisterAccount();

                if (allowRegisterAccount != null && allowRegisterAccount.isWeChat()) {
                    user = new User();
                    user.setUserName(userManage.queryUserIdentifier(40) + "-" + UUIDUtil.getUUID22());//会员用户名
                    user.setSalt(UUIDUtil.getUUID32());//盐值
                    user.setSecurityDigest(new Date().getTime());//安全摘要
                    user.setAllowUserDynamic(true);//是否允许显示用户动态
                    user.setRealNameAuthentication(false);//是否实名认证
                    user.setRegistrationDate(new Date());//注册日期
                    user.setPoint(0L);//当前积分
                    user.setDeposit(new BigDecimal("0"));//当前预存款
                    user.setType(40);//用户类型 40:微信用户
                    user.setPlatformUserId(platformUserId);//平台用户Id
                    user.setState(1);//用户状态    1:正常用户
                    user.setUserVersion(0);//版本号


                    try {
                        userService.saveUser(user, null, null);
                    } catch (Exception e) {
                        error.put("register", ErrorView._823.name());//注册会员出错
                        // TODO Auto-generated catch block
                        //e.printStackTrace();
                    }
                } else {//如果不允许注册
                    error.put("register", ErrorView._862.name());//不允许注册


                }


            }
        }


        //自动登录
        if (error.size() == 0 && user != null) {

            if (user.getState().equals(1)) {
                //写入登录日志
                UserLoginLog userLoginLog = new UserLoginLog();
                userLoginLog.setId(userLoginLogManage.createUserLoginLogId(user.getId()));
                userLoginLog.setIp(IpAddress.getClientIpAddress(request));
                userLoginLog.setUserId(user.getId());
                userLoginLog.setTypeNumber(10);//登录
                userLoginLog.setLogonTime(new Date());
                Object new_userLoginLog = userLoginLogManage.createUserLoginLogObject(userLoginLog);
                userService.saveUserLoginLog(new_userLoginLog);


                //访问令牌
                String accessToken = UUIDUtil.getUUID32();
                //刷新令牌
                String refreshToken = UUIDUtil.getUUID32();

                if (openId != null && !"".equals(openId.trim())) {
                    oAuthManage.addOpenId(openId, refreshToken);
                }

                oAuthManage.addAccessToken(accessToken, new AccessUser(user.getId(), user.getUserName(), user.getNickname(), fileManage.fileServerAddress() + user.getAvatarPath(), user.getAvatarName(), user.getSecurityDigest(), false, openId));
                oAuthManage.addRefreshToken(refreshToken, new RefreshUser(accessToken, user.getId(), user.getUserName(), user.getNickname(), fileManage.fileServerAddress() + user.getAvatarPath(), user.getAvatarName(), user.getSecurityDigest(), false, openId));

                //将访问令牌添加到Cookie
                WebUtil.addCookie(response, "cms_accessToken", accessToken, 0);
                //将刷新令牌添加到Cookie
                WebUtil.addCookie(response, "cms_refreshToken", refreshToken, 0);
                AccessUserThreadLocal.set(new AccessUser(user.getId(), user.getUserName(), user.getNickname(), fileManage.fileServerAddress() + user.getAvatarPath(), user.getAvatarName(), user.getSecurityDigest(), false, openId));

                //删除缓存
                userManage.delete_cache_findUserById(user.getId());
                userManage.delete_cache_findUserByUserName(user.getUserName());

                //异步执行会员卡赠送任务(长期任务类型)
                membershipCardGiftTaskManage.async_triggerMembershipCardGiftTask(user.getUserName());

            } else {
                error.put("register", ErrorView._824.name());//禁止用户
            }


        }

    }

}
